#!/usr/bin/perl -w
use strict;
$| = 1;

#
#       Copyright (C) 2008-2012 Александр Девяткин, "Зелёная горка"
#
#       Разрешается повторное распространение и использование как в виде исходного
#       кода, так и в двоичной форме, с изменениями или без, при соблюдении следующих
#       условий:
#
#       * При повторном распространении исходного кода должно оставаться указанное
#         выше уведомление об авторском праве, этот список условий и последующий
#         отказ от гарантий.
#       * При повторном распространении двоичного кода должна сохраняться указанная
#         выше информация об авторском праве, этот список условий и последующий отказ
#         от гарантий в документации и/или в других материалах, поставляемых при
#         распространении.
#       * Ни название "Зелёная горка", ни имена ее сотрудников не могут быть
#         использованы в качестве поддержки или продвижения продуктов, основанных
#         на этом ПО без предварительного письменного разрешения.
#
#       ЭТА ПРОГРАММА ПРЕДОСТАВЛЕНА ВЛАДЕЛЬЦАМИ АВТОРСКИХ ПРАВ И/ИЛИ ДРУГИМИ СТОРОНАМИ
#	"КАК ОНА ЕСТЬ" БЕЗ КАКОГО-ЛИБО ВИДА ГАРАНТИЙ, ВЫРАЖЕННЫХ ЯВНО ИЛИ ПОДРАЗУМЕВАЕМЫХ,
#	ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ПОДРАЗУМЕВАЕМЫЕ ГАРАНТИИ КОММЕРЧЕСКОЙ ЦЕННОСТИ
#	И ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. НИ В КОЕМ СЛУЧАЕ, ЕСЛИ НЕ ТРЕБУЕТСЯ
#	СООТВЕТСТВУЮЩИМ ЗАКОНОМ, ИЛИ НЕ УСТАНОВЛЕНО В УСТНОЙ ФОРМЕ, НИ ОДИН ВЛАДЕЛЕЦ
#	АВТОРСКИХ ПРАВ И НИ ОДНО ДРУГОЕ ЛИЦО, КОТОРОЕ МОЖЕТ ИЗМЕНЯТЬ И/ИЛИ ПОВТОРНО
#	РАСПРОСТРАНЯТЬ ПРОГРАММУ, КАК БЫЛО СКАЗАНО ВЫШЕ, НЕ НЕСЁТ ОТВЕТСТВЕННОСТИ,
#	ВКЛЮЧАЯ ЛЮБЫЕ ОБЩИЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ ИЛИ ПОСЛЕДОВАВШИЕ УБЫТКИ,
#	ВСЛЕДСТВИЕ ИСПОЛЬЗОВАНИЯ ИЛИ НЕВОЗМОЖНОСТИ ИСПОЛЬЗОВАНИЯ ПРОГРАММЫ (ВКЛЮЧАЯ,
#	НО НЕ ОГРАНИЧИВАЯСЬ ПОТЕРЕЙ ДАННЫХ, ИЛИ ДАННЫМИ, СТАВШИМИ НЕПРАВИЛЬНЫМИ, ИЛИ
#	ПОТЕРЯМИ ПРИНЕСЕННЫМИ ИЗ-ЗА ВАС ИЛИ ТРЕТЬИХ ЛИЦ, ИЛИ ОТКАЗОМ ПРОГРАММЫ РАБОТАТЬ
#	СОВМЕСТНО С ДРУГИМИ ПРОГРАММАМИ), ДАЖЕ ЕСЛИ ТАКОЙ ВЛАДЕЛЕЦ ИЛИ ДРУГОЕ ЛИЦО БЫЛИ
#	ИЗВЕЩЕНЫ О ВОЗМОЖНОСТИ ТАКИХ УБЫТКОВ.
#

#       Copyright (C) 2008-2012 Aleksandr Deviatkin, "Green Hill"
#
#       Redistribution and use in source and binary forms, with or without
#       modification, are permitted provided that the following conditions are
#       met:
#       
#       * Redistributions of source code must retain the above copyright
#         notice, this list of conditions and the following disclaimer.
#       * Redistributions in binary form must reproduce the above
#         copyright notice, this list of conditions and the following disclaimer
#         in the documentation and/or other materials provided with the
#         distribution.
#       * Neither the name of the Green Hill nor the names of its
#         contributors may be used to endorse or promote products derived from
#         this software without specific prior written permission.
#       
#       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#       "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#       LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#       A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#       OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#       SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#       LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#       OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

#
# Получаем текущие данные из счетчика Меркурий-203.2Т
# 2009-03-22 alid
# 2011-08-02 alid
#

use lib "$ENV{MY}/counter";
use Mercury;

my (@args, %opts);
foreach(@ARGV){
   if(/^\-(\S)(.*)/){	$opts{$1} = $2;	} else {	push @args, $_;	}
}
my $verb = exists $opts{v};
my $retries = (exists $opts{r}) ? $opts{r} : 10;
my $showhead = exists $opts{s};	# Показать формат выходных данных
my ($saddr, $device) = (@args);
die "Usage: $0 addr serial-dev"	unless(defined $saddr && $device);

my $addr = sprintf("%08x",$saddr);
$addr =~ s/(\w\w)(\w\w)(\w\w)(\w\w)/$1 $2 $3 $4/;
print "Addr: [$addr]\n"	if $verb;

my $STALL_DEFAULT=2;	# how many seconds to wait for new input
my $MAXLENGTH = 255;	# наибольшая длина пакета

my ($status,$cnt,@data);
my $connect = Mercury->new($device,'M203',$addr,'','',$retries,$verb);

if($verb) {
	print "Connection testing ... "	if $verb;
	$status = $connect->tst();
	print "$status\n"	if $verb;
	die	"[".hex($addr)."] Connection failed: [$status]"	unless($status=~/ok/);
}

my $Data;

#
# Накопленная энергия
#
print "Stored energy ########################\n"	if $verb;
($status,$cnt,@data) = $connect->get('27');

die "[$addr] [$device] 27h request failed: [$status]"	unless($status=~/ok/);
print "[$status][$cnt][".join(' ',@data)."]\n"	if $verb;

my @a;
foreach my $i (5,9) {
	my $num = join("",$data[0+$i],$data[1+$i],$data[2+$i],$data[3+$i]);
	push @{$Data->{se}}, $num/100;
}
print "se [27h]: ".join(' ',@{$Data->{se}})."\n"	if $verb;

#
# Текущие параметры
#
print "Monitoring ########################\n"	if $verb;
# мощность
($status,$cnt,@data) = $connect->get('26');

die "[".hex($addr)."] 26h request failed: [$status]"	unless($status=~/ok/);
print "[$status][$cnt][".join(' ',@data)."]\n"	if $verb;
push @{$Data->{mp}}, join("",$data[5],$data[6])/100;
print "mp [26h]: ".join(' ',@{$Data->{mp}})."\n"	if $verb;

# частота
($status,$cnt,@data) = $connect->get('81');

die "[".hex($addr)."] 81h request failed: [$status]"	unless($status=~/ok/);
print "[$status][$cnt][".join(' ',@data)."]\n"	if $verb;
push @{$Data->{mf}}, join("",$data[5],$data[6])/100;
print "mf [81h]: ".join(' ',@{$Data->{mf}})."\n"	if $verb;

# напряжение, ток, мощность (1 сек)
($status,$cnt,@data) = $connect->get('63');
die "[".hex($addr)."] 63h request failed: [$status]"	unless($status=~/ok/);
print "[$status][$cnt][".join(' ',@data)."]\n"	if $verb;
push @{$Data->{mv}}, join("",$data[5],$data[6])/10;
print "mv [63h]: ".join(' ',@{$Data->{mv}})."\n"	if $verb;
push @{$Data->{mc}}, join("",$data[7],$data[8])/10;
print "mv [63h]: ".join(' ',@{$Data->{mc}})."\n"	if $verb;
push @{$Data->{ms}}, join("",$data[9],$data[10],$data[11])/10;
print "ms [63h]: ".join(' ',@{$Data->{ms}})."\n"	if $verb;

###### data output
print "addr;mv1;mc1;mf;mps;mss;se1ai;se2ai\n"	if($showhead);
print "$saddr;".$Data->{mv}[0].";".
	$Data->{mc}[0].";".
	$Data->{mf}[0].";".
	$Data->{mp}[0].";".		# Мощность P
	$Data->{ms}[0].";".		# Мощность S
	join(";",@{$Data->{se}}).
	"\n";

$connect->quit();
